import 'dart:developer';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:lib_http/lib_http.dart';

class BodyConfigPage extends StatefulWidget {
  final dynamic data;

  const BodyConfigPage(this.data, {super.key});

  @override
  State<BodyConfigPage> createState() => _BodyConfigPageState();
}

class _BodyConfigPageState extends State<BodyConfigPage> {
  // map数据
  static const int mapType = 1;

  // 文本，文件结合数据
  static const int formDataType = 2;

  // 单文本数据
  static const int textType = 3;

  int dataType = formDataType;

  List<Param> mapData = [];

  List<Param> formFieldData = [];

  String textData = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
            leading: GestureDetector(
                child:
                    Container(width: kToolbarHeight, color: Colors.transparent, child: const Icon(Icons.arrow_back, color: Colors.black87)),
                onTap: () => Navigator.pop(context)),
            backgroundColor: Colors.white,
            elevation: 1.0,
            shadowColor: Colors.black26,
            actions: [_buildSaveAction(context)],
            centerTitle: true,
            title: const Text("Body Config", style: TextStyle(color: Colors.black87, fontSize: 18.0, fontWeight: FontWeight.w500))),
        body: _buildRequestBody());
  }

  Widget _buildSaveAction(BuildContext context) {
    return GestureDetector(
        child: Container(
            width: kToolbarHeight,
            color: Colors.transparent,
            alignment: Alignment.center,
            child: const Text("保存", style: TextStyle(color: Colors.blue))),
        onTap: () {
          FocusScope.of(context).requestFocus(FocusNode());
          _saveConfig(context);
        });
  }

  Widget _buildRequestBody() {
    List<Widget> children = [];
    children.add(_buildBodyTypeSelect());
    if (dataType == mapType) {
      children.add(_buildUrlEncodedTypeBody());
    }
    if (dataType == formDataType) {
      children.add(_buildFormDataTypeBody());
    }
    if (dataType == textType) {
      children.add(_buildTextTypeBody());
    }
    return Column(crossAxisAlignment: CrossAxisAlignment.start, children: children);
  }

  Widget _buildBodyTypeSelect() {
    return GestureDetector(
        child: Container(
            height: 42,
            decoration: BoxDecoration(color: Colors.black.withOpacity(0.05), borderRadius: BorderRadius.circular(8.0)),
            margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
            padding: const EdgeInsets.symmetric(horizontal: 10.0),
            child: Row(mainAxisSize: MainAxisSize.min, children: [
              Text(dataType == mapType
                  ? "x-www-urlencoded"
                  : dataType == formDataType
                      ? "form-data"
                      : "raw"),
              const SizedBox(width: 10.0),
              const Icon(Icons.keyboard_arrow_down, color: Colors.black54)
            ])),
        onTap: () {
          _showChooseBodyTypeDialog();
        });
  }

  Widget _buildUrlEncodedTypeBody() {
    List<Widget> children = [];
    children.add(Container(
        height: 40.0,
        margin: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
        decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.05),
            borderRadius: const BorderRadius.only(topLeft: Radius.circular(4.0), topRight: Radius.circular(4.0))),
        child: Row(children: [
          const Expanded(
              child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 10.0),
            child: Text("Key", textAlign: TextAlign.left, style: TextStyle(fontWeight: FontWeight.bold)),
          )),
          Container(width: 1.0, height: 20.0, color: Colors.black12),
          const Expanded(
              child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 10.0),
            child: Text("Value", textAlign: TextAlign.left, style: TextStyle(fontWeight: FontWeight.bold)),
          )),
          const SizedBox(width: 30.0)
        ])));
    for (Param element in mapData) {
      children.add(Container(
          height: 48.0,
          margin: const EdgeInsets.symmetric(horizontal: 8.0),
          decoration: BoxDecoration(border: Border.all(color: Colors.black.withOpacity(0.05))),
          child: Row(children: [
            Expanded(
                child: TextField(
                    controller: TextEditingController(text: element.key),
                    onChanged: (value) {
                      element.key = value;
                    },
                    style: const TextStyle(fontSize: 15.0),
                    decoration: const InputDecoration(
                        hintText: "Key", border: InputBorder.none, contentPadding: EdgeInsets.symmetric(horizontal: 10.0)))),
            Container(width: 0.5, color: Colors.black12),
            Expanded(
                child: TextField(
                    controller: TextEditingController(text: element.value),
                    onChanged: (value) {
                      element.value = value;
                    },
                    style: const TextStyle(fontSize: 15.0),
                    decoration: const InputDecoration(
                        hintText: "Value", border: InputBorder.none, contentPadding: EdgeInsets.symmetric(horizontal: 10.0)))),
            GestureDetector(
                child: const SizedBox(width: 30.0, child: Icon(Icons.remove, color: Colors.blue)),
                onTap: () {
                  mapData.remove(element);
                  setState(() {});
                })
          ])));
    }
    children.add(Center(
        child: GestureDetector(
            child: Container(
                margin: const EdgeInsets.all(6.0),
                padding: const EdgeInsets.all(6.0),
                decoration: const BoxDecoration(color: Colors.blue, shape: BoxShape.circle),
                child: const Icon(Icons.add, color: Colors.white)),
            onTap: () {
              mapData.add(Param("", 1));
              setState(() {});
            })));
    return ListView(padding: const EdgeInsets.only(bottom: 20.0), shrinkWrap: true, children: children);
  }

  Widget _buildFormDataTypeBody() {
    List<Widget> children = [];
    children.add(Container(
        height: 40.0,
        margin: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0),
        decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.05),
            borderRadius: const BorderRadius.only(topLeft: Radius.circular(4.0), topRight: Radius.circular(4.0))),
        child: Row(children: [
          const Expanded(
              child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 10.0),
            child: Text("Key", textAlign: TextAlign.left, style: TextStyle(fontWeight: FontWeight.bold)),
          )),
          Container(width: 1.0, height: 20.0, color: Colors.black12),
          const Expanded(
              child: Padding(
                  padding: EdgeInsets.symmetric(horizontal: 10.0),
                  child: Text("Value", textAlign: TextAlign.left, style: TextStyle(fontWeight: FontWeight.bold)))),
          const SizedBox(width: 30.0)
        ])));
    for (Param element in formFieldData) {
      children.add(Container(
          height: 48.0,
          margin: const EdgeInsets.symmetric(horizontal: 8.0),
          decoration: BoxDecoration(border: Border.all(color: Colors.black.withOpacity(0.05))),
          child: Row(children: [
            Expanded(
                child: Row(children: [
              Expanded(
                  child: TextField(
                      controller: TextEditingController(text: element.key),
                      onChanged: (value) {
                        element.key = value;
                      },
                      style: const TextStyle(fontSize: 15.0),
                      decoration: const InputDecoration(
                          hintText: "Key", border: InputBorder.none, contentPadding: EdgeInsets.symmetric(horizontal: 10.0)))),
              GestureDetector(
                  child: Container(
                      margin: const EdgeInsets.only(right: 4.0),
                      padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),
                      decoration: BoxDecoration(color: Colors.black.withOpacity(0.05), borderRadius: BorderRadius.circular(5.0)),
                      child: Text(element.type == 1 ? "Text" : "File")),
                  onTap: () {
                    _showChooseDataTypeDialog(element);
                  })
            ])),
            Container(width: 0.5, color: Colors.black12),
            element.type == 1
                ? Expanded(
                    child: TextField(
                        controller: TextEditingController(text: element.value ?? ""),
                        onChanged: (value) {
                          element.value = value;
                        },
                        style: const TextStyle(fontSize: 15.0),
                        decoration: const InputDecoration(
                            hintText: "Value", border: InputBorder.none, contentPadding: EdgeInsets.symmetric(horizontal: 10.0))))
                : Expanded(
                    child: GestureDetector(
                        child: TextField(
                            controller: TextEditingController(text: element.file?.filename ?? ""),
                            enabled: false,
                            style: const TextStyle(fontSize: 15.0),
                            decoration: const InputDecoration(
                                hintText: "Select File", border: InputBorder.none, contentPadding: EdgeInsets.symmetric(horizontal: 10.0))),
                        onTap: () {
                          _chooseFile(element);
                        })),
            GestureDetector(
                child: const SizedBox(width: 30.0, child: Icon(Icons.remove, color: Colors.blue)),
                onTap: () {
                  formFieldData.remove(element);
                  setState(() {});
                })
          ])));
    }
    children.add(Center(
        child: GestureDetector(
            child: Container(
                margin: const EdgeInsets.all(6.0),
                padding: const EdgeInsets.all(6.0),
                decoration: const BoxDecoration(color: Colors.blue, shape: BoxShape.circle),
                child: const Icon(Icons.add, color: Colors.white)),
            onTap: () {
              formFieldData.add(Param("", 1));
              setState(() {});
            })));
    return ListView(padding: const EdgeInsets.only(bottom: 20.0), shrinkWrap: true, children: children);
  }

  Widget _buildTextTypeBody() {
    return Container(
        margin: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 10.0),
        decoration: BoxDecoration(color: Colors.black.withOpacity(0.05), borderRadius: BorderRadius.circular(4.0)),
        child: TextField(
            maxLines: 15,
            controller: TextEditingController(text: textData),
            onChanged: (value) {
              textData = value;
            },
            decoration:
                const InputDecoration(border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 10.0))));
  }

  void _showChooseDataTypeDialog(Param element) {
    FocusScope.of(context).requestFocus(FocusNode());
    showModalBottomSheet(
            context: context,
            builder: (context) {
              var typeList = [1, 2]
                  .map((type) => GestureDetector(
                      child: Container(
                          height: 48.0,
                          alignment: Alignment.center,
                          margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
                          decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(4.0)),
                          child: Text(type == 1 ? "Text" : "File", style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0))),
                      onTap: () {
                        Navigator.pop(context, type);
                      }))
                  .toList();
              typeList.add(GestureDetector(
                  child: Container(
                      height: 48.0,
                      alignment: Alignment.center,
                      margin: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 16.0, top: 5.0),
                      decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(4.0)),
                      child: const Text("Cancel", style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0, color: Colors.black45))),
                  onTap: () {
                    Navigator.pop(context);
                  }));
              return Column(mainAxisSize: MainAxisSize.min, children: typeList);
            },
            backgroundColor: Colors.transparent,
            barrierColor: Colors.black.withOpacity(0.05))
        .then((value) {
      if (value is int) {
        element.type = value;
        element.value = null;
        element.file = null;
        setState(() {});
      }
    });
  }

  void _showChooseBodyTypeDialog() {
    FocusScope.of(context).requestFocus(FocusNode());
    showModalBottomSheet(
            context: context,
            builder: (context) {
              var typeList = [mapType, formDataType, textType]
                  .map((type) => GestureDetector(
                      child: Container(
                          height: 48.0,
                          alignment: Alignment.center,
                          margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
                          decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(4.0)),
                          child: Text(
                              type == mapType
                                  ? "x-www-urlencoded"
                                  : type == formDataType
                                      ? "form-data"
                                      : "raw",
                              style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0))),
                      onTap: () {
                        Navigator.pop(context, type);
                      }))
                  .toList();
              typeList.add(GestureDetector(
                  child: Container(
                      height: 48.0,
                      alignment: Alignment.center,
                      margin: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 16.0, top: 5.0),
                      decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(4.0)),
                      child: const Text("Cancel", style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16.0, color: Colors.black45))),
                  onTap: () {
                    Navigator.pop(context);
                  }));
              return Column(mainAxisSize: MainAxisSize.min, children: typeList);
            },
            backgroundColor: Colors.transparent,
            barrierColor: Colors.black.withOpacity(0.05))
        .then((value) {
      if (value is int) {
        dataType = value;
        setState(() {});
      }
    });
  }

  void _saveConfig(BuildContext context) {
    dynamic result;
    if (dataType == textType) {
      result = textData;
    }
    if (dataType == mapType) {
      Map<String, dynamic> data = {};
      for (Param element in mapData) {
        data[element.key] = element.value;
      }
      result = data;
    }
    if (dataType == formDataType) {
      Map<String, dynamic> data = {};
      for (Param element in formFieldData) {
        if(element.type == 1) {
          data[element.key] = element.value;
        } else {
          data[element.key] = element.file;
        }
      }
      result = FormData.fromMap(data);
    }
    log("Body参数类型:${result.runtimeType},Body参数:$result");
    Navigator.pop(context, result);
  }

  @override
  void initState() {
    super.initState();
    var data = widget.data;
    log("Body参数类型:${data.runtimeType},Body参数:$data");
    if (data is Map<String, dynamic>) {
      dataType = mapType;
      mapData.clear();
      data.forEach((key, value) {
        mapData.add(Param(key, 1)..value = value);
      });
    } else if (data is FormData) {
      dataType = formDataType;
      formFieldData.clear();
      formFieldData.addAll(data.fields.map((field) => Param(field.key, 1)..value = field.value).toList());
      formFieldData.addAll(data.files.map((file) => Param(file.key, 2)..file = file.value).toList());
    } else {
      dataType = textType;
      textData = data?.toString() ?? textData;
    }
  }

  void _chooseFile(Param element) async {
    FilePickerResult? result = await FilePicker.platform.pickFiles();
    if (result != null) {
      PlatformFile file = result.files.single;
      log("选择文件返回结果:$file");
      if (kIsWeb) {
        element.file = MultipartFile.fromBytes(file.bytes!, filename: file.name);
      } else {
        element.file = await MultipartFile.fromFile(file.path!, filename: file.name);
      }
    }
    setState(() {});
  }
}

class Param {
  String key;
  int type;
  String? value;
  MultipartFile? file;

  Param(this.key, this.type);
}
